package cn.atcoder.air.transport;

import cn.atcoder.air.server.ServerChannelHandler;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.serialization.ClassResolvers;
import io.netty.handler.codec.serialization.ObjectDecoder;
import io.netty.handler.codec.serialization.ObjectEncoder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.TimeUnit;

/**
 * @author yangjunda1
 * @description
 * @date 5/9/19 7:20 PM
 */
public class TcpServerTransport implements ServerTransport {

    private static final Logger LOGGER = LoggerFactory.getLogger(TcpServerTransport.class);

    public TcpServerTransport(int port) {
        this.port = port;
    }

    private int port;

    @Override
    public Boolean start() {
        boolean flag = Boolean.FALSE;
        LOGGER.debug("Server transport start! ");
        EventLoopGroup boss = new NioEventLoopGroup();
        EventLoopGroup worker = new NioEventLoopGroup();
        ServerBootstrap bootstrap = new ServerBootstrap();
        bootstrap.group(boss, worker);
        bootstrap.channel(NioServerSocketChannel.class);
        bootstrap.option(ChannelOption.SO_BACKLOG, 128);
        // 通过NoDelay禁用Nagle,使消息立即发出去，不用等待到一定的数据量才发出去
        bootstrap.option(ChannelOption.TCP_NODELAY, true);
        // 保持长连接状态
        bootstrap.childOption(ChannelOption.SO_KEEPALIVE, true);
        bootstrap.childHandler(new ChannelInitializer<SocketChannel>() {
            @Override
            protected void initChannel(SocketChannel socketChannel) throws Exception {
                ChannelPipeline p = socketChannel.pipeline();
                p.addLast(new ObjectEncoder());
                p.addLast(new ObjectDecoder(ClassResolvers.cacheDisabled(null)));
                p.addLast(new ServerChannelHandler());
            }
        });
        try {
            ChannelFuture channelFuture = bootstrap.bind(port).sync();
            channelFuture.await(3000, TimeUnit.MILLISECONDS);
            if (channelFuture.isSuccess()) {
                flag = Boolean.TRUE;
            }

        } catch (InterruptedException e) {
            LOGGER.error(e.getMessage(), e);
        }
        return flag;
    }

    @Override
    public void stop() {

    }
}
